import java.awt.Component;
import java.io.*;
import java.util.*;

public class InputData {
	
	//data members
	private ArrayList<boolean[]> boolMatrix;
	private ArrayList<int[]> intMatrix;
	private HashMap<Integer, ArrayList<Integer>> neighbors;
	private int maxNumber;
	
	/**
	 * add a new neighbor
	 * @param i - 1st neighbor
	 * @param j - 2nd neighbor
	 */
	private void addNeighbor(int i, int j){
		if (!neighbors.containsKey(i))
			neighbors.put(i, new ArrayList<Integer>());
		if (!neighbors.get(i).contains(j))
			neighbors.get(i).add(j);
	}
	
	/**
	 * get the neighbors of the node in the parameter
	 * @param i - a node
	 * @return - the neighbors of the i'th node
	 */
	public ArrayList<Integer> getNeighbors(int i){
		return neighbors.get(i);
	}
	
	/**
	 * get the max number in the input file
	 * @return the max number in the input file
	 */
	public int getMaxNumber(){
		return maxNumber;
	}
	
	/**
	 * replace the string from the file to a int array
	 * @param str - the input string from the file
	 * @return an int array (same as the input text row)
	 */
	private int[] replaceArr(String[] str){
		int[] intArr = new int[str.length];
		for (int i=0;i<str.length;i++)
			intArr[i]=Integer.parseInt(str[i]);
		return intArr;
	}
	
	/**
	 * print the colored table
	 * @param arr - a coloring array that gives a color to each area
	 */
	public void showColordTable(List<Integer> arr){
		showColordTable(arr, null);
	}
	
	/**
	 * print the colored table in a specific component
	 * @param arr - a coloring array that gives a color to each area
	 * @param c - the component to show the colored table
	 */
	public void showColordTable(List<Integer> arr, Component c){
		Grid g = new Grid(intMatrix.size(),intMatrix.get(0).length, c);
		
		for (int i=0;i<intMatrix.size();i++)
			for (int j=0;j<intMatrix.get(0).length;j++)
				g.setColor(i, j, arr.get(intMatrix.get(i)[j]));
		
		g.show();
	}
	
	
	/**
	 * check if there is a link between i and j 
	 */
	public boolean check(int i, int j){
		return boolMatrix.get(i)[j];
	}
	
	/**
	 * get the maximal number of neighbors
	 * @return the maximal number of neighbors
	 */
	public int getMaxError() {
		int maxError = 0;
		
		for (int i = 0; i <= maxNumber; ++i) {
			if (getNeighbors(i) != null)
				maxError += getNeighbors(i).size();
		}
		
		return maxError;
	}
	
	/**
	 * constructor
	 * @param fileLocation - path for the input file
	 */
	public InputData(String fileLocation){
		File file = new File(fileLocation);
	    FileInputStream fis = null;
	    BufferedInputStream bis = null;
	    BufferedReader reader = null;
	    DataInputStream dis = null;
	    String line;
	    int[] lineArr;
	    int lineSize=0;
	    neighbors = new HashMap<Integer, ArrayList<Integer>>();
	    intMatrix = new ArrayList<int[]>();
	    boolMatrix = new ArrayList<boolean[]>();
	    
	    try {
	        fis = new FileInputStream(file);

	        // Here BufferedInputStream is added for fast reading.
	        bis = new BufferedInputStream(fis);
	        dis = new DataInputStream(bis);
	        
	        reader = new BufferedReader(new InputStreamReader(bis));

	        //while file isn't empty...
	        while (reader.ready()) {

	          // this statement reads the line from the file and print it to
	          // the console.
	        	line = reader.readLine();
	        	lineArr = replaceArr(line.split(String.valueOf('\t')));
	        	intMatrix.add(lineArr);
	        	for (int i=0;i<lineArr.length;i++)
	        		maxNumber = Math.max(maxNumber, lineArr[i]);
	        }
	        
	        // dispose all the resources after using them.
	        fis.close();
	        bis.close();
	        dis.close();
	        reader.close();

	        //after reading the file
	        for (int i=0;i<maxNumber+1;i++){
	        	boolMatrix.add(new boolean[maxNumber+1]);
	        }
	        
	        lineSize=intMatrix.get(0).length;
	        
	        for (int i=0;i<intMatrix.size()-1;i++)
	        	for (int j=0;j<lineSize-1;j++){
	        		if (intMatrix.get(i)[j]!=intMatrix.get(i)[j+1]){
	        			boolMatrix.get(intMatrix.get(i)[j])[intMatrix.get(i)[j+1]]=true;
	        			addNeighbor(intMatrix.get(i)[j], intMatrix.get(i)[j+1]);
	        			boolMatrix.get(intMatrix.get(i)[j+1])[intMatrix.get(i)[j]]=true;
	        			addNeighbor(intMatrix.get(i)[j+1], intMatrix.get(i)[j]);
	        		}
	        		if (intMatrix.get(i)[j]!=intMatrix.get(i+1)[j]){
	        			boolMatrix.get(intMatrix.get(i)[j])[intMatrix.get(i+1)[j]]=true;
	        			addNeighbor(intMatrix.get(i)[j], intMatrix.get(i+1)[j]);
	        			boolMatrix.get(intMatrix.get(i+1)[j])[intMatrix.get(i)[j]]=true;
	        			addNeighbor(intMatrix.get(i+1)[j], intMatrix.get(i)[j]);
	        		}	
	        	}
	        
	        for (int i=0;i<intMatrix.size()-1;i++)
	        	if (intMatrix.get(i)[lineSize-1]!=intMatrix.get(i+1)[lineSize-1]){
        			boolMatrix.get(intMatrix.get(i)[lineSize-1])[intMatrix.get(i+1)[lineSize-1]]=true;
        			addNeighbor(intMatrix.get(i)[lineSize-1], intMatrix.get(i+1)[lineSize-1]);
        			boolMatrix.get(intMatrix.get(i+1)[lineSize-1])[intMatrix.get(i)[lineSize-1]]=true;
        			addNeighbor(intMatrix.get(i+1)[lineSize-1], intMatrix.get(i)[lineSize-1]);
        		}
	        
	        for (int i=0;i<lineSize-1;i++)
	        	if (intMatrix.get(intMatrix.size()-1)[i]!=intMatrix.get(intMatrix.size()-1)[i+1]){
        			boolMatrix.get(intMatrix.get(intMatrix.size()-1)[i])[intMatrix.get(intMatrix.size()-1)[i+1]]=true;
        			addNeighbor(intMatrix.get(intMatrix.size()-1)[i], intMatrix.get(intMatrix.size()-1)[i+1]);
        			boolMatrix.get(intMatrix.get(intMatrix.size()-1)[i+1])[intMatrix.get(intMatrix.size()-1)[i]]=true;
        			addNeighbor(intMatrix.get(intMatrix.size()-1)[i+1], intMatrix.get(intMatrix.size()-1)[i]);
        		}
	        
	      } catch (FileNotFoundException e) {
	        e.printStackTrace();
	      } catch (IOException e) {
	        e.printStackTrace();
	      }
	}
}
